package run;

import java.awt.Container;
import java.util.LinkedList;
import java.util.List;

import processing.core.PApplet;
import processing.core.PVector;

public class LineCell {
	
	int generation;
	PVector loc;
	PVector dir;
	PApplet p;
	private boolean dead = false;
	SandPainter paint;
	List<PVector> pastLocs;
	List<DirChanger> dirChangers = new LinkedList();
	
	List<DistRule> distRules = new LinkedList();
	
	private List<CollideRule> collideRules = new LinkedList();

	int r,g,b;
	
	public LineCell(PVector pVector, PVector dir, PApplet p, int gen) {
		loc = pVector;
		this.dir = dir;
		dir.normalize();
		this.generation = gen;
		this.p = p;
		paint = new SandPainter(p);
		pastLocs = new LinkedList<PVector>();
		
		
		collideRules.add(new RandomPastPerpendicularSpawnRule());
		collideRules.add(new InflectionDirectionRule());
		distRules.add(new RepulseRule());
		
		r = (int) p.random(100,170);
		g = (int) p.random(40,110);
		b = (int) p.random(50,150);
	}
	
	public void move( Env e) {
		
		if (dead) return;
		
	    float z = 0.43F;
	    
	    // draw black crack
	    p.stroke(r,g,b,85);
	    
	    float x = loc.x;
	    float y = loc.y;
	    
	    p.point(x+random(-z,z),y+random(-z,z));
	    p.point(x+random(-z,z),y+random(-z,z));
	    p.point(x+random(-z,z),y+random(-z,z));
	    p.point(x+random(-z,z),y+random(-z,z));
	    
	    
	    // draw the hazy line
	    for (int i = 0; i < 7; i++) {
	      p.stroke(r,g,b, random(30,40));
	      p.point(x+random(-5*z, 5*z), y+random(-5*z, 5*z));
	    }
	    
	    //paint.render( loc.x+20, loc.y+20, loc.x, loc.y, p);
	    
	    // Direction Changers?
	    for (DirChanger d : dirChangers) {
	    	d.changeDir(dir);
	    }
	    
	    // Distance-related rules
	    for (LineCell c : e.cells) {
		    for (DistRule d : distRules) {
//		    	d.execRule(this, c, e, p);
		    }
	    }
	    
	    //TODO think of a good way to threshold it... we want more interesting shit happening
	    // in the emptier spaces.
//	    System.out.println(dir);
	    dir.normalize();
	    loc.add(dir);
	    
	    // what's a fast way to detect collisions?
	    // perhaps... whenever we change direction, we simply place a
	    // point down. ... ugh
	    if (loc.x < 0 || loc.y<0 || loc.x>900 || loc.y > 500) {
	    	dead=true;
	    	loc = new PVector(0,0,0);
	    }

	    // COLLISION
	    LineCell collided = e.isCollide(this);
	    if (collided != null) {
	    	dead=true;
	    	// pick random past locs to spawn!
	    	for (CollideRule r : collideRules) {
	    		r.executeRule(this, collided, e, p);
	    	}
	    }
	  
	    addLocalHist(this.loc);
	    e.addHist(this, this.loc);
	}

	private void addLocalHist(PVector loc2) {
		pastLocs.add(new PVector(loc2.x, loc2.y, 0));
	}

	private float random(float x, float y) {
		return p.random(x,y);
	}

	public void addDirChanger(DirChanger d) {
		dirChangers.add(d);
	}
	
	
}
